﻿#nullable enable

using Furion.DatabaseAccessor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using System.ComponentModel;
using System.Reflection;

namespace Admin.NET.Core
{
    public static class TypeUtil
    {
        /// <summary>
        /// 获取类型
        /// </summary>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public static Type? GetType(string typeName)
        {
            return Type.GetType(typeName);
        }

        /// <summary>
        /// 根据实体获取其导航类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<TableColumn> GetNavigationColumns(IEntityType? type)
        {
            if (type == null) { return new(); }

            var navigationColumns = type.ClrType.GetProperties()
                .Select(propertyInfo => type?.FindNavigation(propertyInfo.Name))
                .Where(p => p != null)
                .Select(p =>
                {
                    var pInfo = p?.PropertyInfo;
                    var pType = pInfo?.PropertyType;
                    string dataType = pType?.ToString() ?? "";
                    return new TableColumn
                    {
                        IsRequired = FieldUtil.IsRequired(p??null!, dataType),
                        ColumnName = p?.Name ?? "",
                        ColumnKey = false.ToString(),
                        DataType = dataType,
                        NetType = CodeGenUtil.ConvertDataType(dataType),
                        ColumnComment = p?.GetComment() ?? "",
                        FieldType = FieldType.NAVIGATION.GetDescription()
                    };
                }).ToList();
            return navigationColumns ?? null!;
        }

        /// <summary>
        /// 根据实体获取其指示类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<TableColumn> GetUniqueColumns(IEntityType? type)
        {
            if (type == null) { return new(); }

            var propInfos = new List<PropertyInfo>();

            type.ClrType.GetProperties().ToList().ForEach(x => x.GetCustomAttributes(false).ToList().ForEach(y =>
            {
                if ("Admin.NET.Core.UniqueAttribute".Equals(y.ToString()))
                {
                    propInfos.Add(x);
                }
            }));

            var uniqueColumns = propInfos.Select(p => new TableColumn
            {
                IsRequired = false,
                ColumnName = p.Name,
                ColumnKey = false.ToString(),
                DataType = p.PropertyType.ToString(),
                NetType = CodeGenUtil.ConvertDataType(p.PropertyType.ToString()),
                ColumnComment = p.GetCustomAttribute<CommentAttribute>()?.Comment ?? "",
                FieldType = FieldType.NO_MAP.GetDescription()
            }).ToList();

            return uniqueColumns ?? null!;
        }


        /// <summary>
        /// 根据实体获取其指示类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<TableColumn> GetNoMapColumns(IEntityType? type)
        {
            if (type == null) { return new(); }

            var propInfos = new List<PropertyInfo>();

            type.ClrType.GetProperties().ToList().ForEach(x => x.GetCustomAttributes(false).ToList().ForEach(y =>
            {
                if ("System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute".Equals(y.ToString()))
                {
                    propInfos.Add(x);
                }
            }));

            var noMapColumns = propInfos.Select(p => new TableColumn
            {
                IsRequired = false,
                ColumnName = p.Name,
                ColumnKey = false.ToString(),
                DataType = p.PropertyType.ToString(),
                NetType = CodeGenUtil.ConvertDataType(p.PropertyType.ToString()),
                ColumnComment = p.GetCustomAttribute<CommentAttribute>()?.Comment ?? "",
                FieldType = FieldType.NO_MAP.GetDescription()
            }).ToList();

            return noMapColumns ?? null!;
        }


        /// <summary>
        /// 根据实体获取其标量类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static List<TableColumn> GetScalarColumns(IEntityType? type)
        {
            if (type == null) { return new(); }

            var propInfos = new List<PropertyInfo>();

            type.ClrType.GetProperties().ToList().ForEach(x => x.GetCustomAttributes(false).ToList().ForEach(y =>
            {
                if ("System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute".Equals(y.ToString()))
                {
                    propInfos.Add(x);
                }
            }));

            var scalarColumns = type.ClrType.GetProperties()
                .Select(propertyInfo => type.FindProperty(propertyInfo.Name))
                .Where(p => p != null)
                .Select(p =>
                {
                    var pInfo = p?.PropertyInfo;
                    var pType = pInfo?.PropertyType;
                    string dataType = pType?.ToString() ?? "";
                    return new TableColumn
                    {


                        IsRequired = FieldUtil.IsRequired(p??null!, dataType),
                        ColumnName = p?.Name??"",
                        ColumnKey = ("Id".Equals(p?.Name)).ToString(),
                        DataType = dataType,
                        NetType = CodeGenUtil.ConvertDataType(dataType),
                        ColumnComment = p?.GetComment() ?? "",
                        FieldType = FieldType.SCALAR.GetDescription()
                    };
                }).ToList();

            return scalarColumns ?? null!;
        }


        /// <summary>
        /// 根据类名获取属性
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static TableInfo? GetTableInfo(IEntityType? type)
        {
            if (type == null) return null;
            return new TableInfo
            {
                TableName = type?.GetDefaultTableName(),
                TableComment = type?.GetComment()
            };
        }


        /// <summary>
        /// 获取枚举类型的备注信息
        /// </summary>
        /// <returns></returns>
        public static string GetColumnRemark(this string typeName)
        {
            Type? type = TypeUtil.GetType(typeName);
            if (type == null) return string.Empty;
            if (!type.IsEnum) return string.Empty;
            var remark = string.Empty;
            foreach (var field in type.GetFields())
            {
                if (field.IsDefined(typeof(DescriptionAttribute), true))
                {
                    var descr = ((DescriptionAttribute?)field.GetCustomAttribute(typeof(DescriptionAttribute), true))?.Description ?? string.Empty;
                    if (!string.IsNullOrEmpty(descr)) remark += descr + ",";
                }
            }
            if (remark.EndsWith(",")) remark = remark[..^1];
            return remark;
        }






    }
}
